package thread;

import lombok.SneakyThrows;

/**
 * 保护性暂停：就是通过一个共享变量，【GuardedObject】，可以使两个线程实现互相通信。而且还可以控制它们的执行顺序。
 */
public class GuardedTest {
    /**
     * Guarded这个类，很像Future的功能了。
     */
    public static void main(String[] args) throws InterruptedException {
        Guarded guarded = new Guarded();

        //线程t1需要一个对象。
        Thread t1 = new Thread("t1"){
            @Override
            public void run() {
                guarded.get();
            }
        };
        t1.start();

        //线程t2写入一个对象。
        Thread t2 = new Thread("t2"){
            @SneakyThrows
            @Override
            public void run() {
                Thread.sleep(2000);
                guarded.put("111");
            }
        };
        t2.start();

        System.out.println("11111开始");
        //在主线程中，调用【t1.join】那么主线程，一定会等待【t1线程结束之后再运行】。
        t1.join();
        System.out.println("22222结束");
    }


    /**
     * join源码：
     * @param millis
     * @throws InterruptedException
     */
//    public final synchronized void join(long millis) throws InterruptedException {
//        long base = System.currentTimeMillis();
//        long now = 0;
//
//        //永久等待。
//        if (millis == 0) {
//            while (isAlive()) {
//                wait(0);
//            }
//        } else {
//            //超时等待。
//            while (isAlive()) {
//                long delay = millis - now;
//                if (delay <= 0) {
//                    break;
//                }
//                wait(delay);
//                now = System.currentTimeMillis() - base;
//            }
//        }
//    }
}


//保护性暂停的一个连接类。
class Guarded{
    //连接的桥梁
    private Object res = null;

    //获取结果：带时间的
    public Object get(long timeout){
        synchronized (this){
            while (res == null){
                try {
                    //超时就直接返回：类似于【Future#get(long)】带时间的暂停。
                    this.wait(timeout);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        //可能返回为空。
        return res;
    }

    //获取结果：不带时间的
    public Object get(){
        synchronized (this){
            while (res == null){
                try {
                    //不带时间的暂停，类似于【Future#get()】
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        //返回的结果。
        return res;
    }

    //设置结果
    public void put(Object o){
        synchronized (this){
            res = o;
            //唤醒等待的所有线程。
            this.notifyAll();
        }
    }

}